#include <Eigen/Dense>
#include <opencv2/core/eigen.hpp>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <time.h>
#include <algorithm>

// using namespace std;
// sally 钝角
// acute 锐角
struct point
{
	/* data */
	int x;
	int y;
};
int isGreenRegion[600][400];
double distance_field[600][400];
double distance_mid[600][400];
double distance_angle1[600][400];
double distance_angle2[600][400];
double my_min(double x, double y)
{
	double tmp;
	tmp = (x > y) ? y : x;
	return tmp;
}
void distance_mid_generate(double field[600][400],point p1,point p2)
{
	Eigen::Vector3d vec,vecX,vecY;
	vec << p2.x-p1.x, p2.y-p1.y,0;
	double tmp;
	for (int i = 0; i < 600; i++)
	{
		for (int j = 0; j < 400; j++)
		{
			vecX << i-p1.x,j-p1.y,0;
			vecY << i-p2.x,j-p2.y,0;
			if (vec.dot(vecX)>0 && vec.dot(vecY)<0)
			{
				tmp = vec.cross(vecX).norm()/vec.norm();
			}
			else
			{
				tmp = my_min(vecX.norm(),vecY.norm());
			}
			field[i][j] = tmp;
		}
		
	}
	
}

void distance_angle_generate(double field[600][400],point p1,point p2)
{
	Eigen::Vector3d vec, vecX;
	vec << p2.x-p1.x,p2.y-p1.y,0;
	double tmp;
	for (int i = 0; i < 600; i++)
	{
		for (int j = 0; j < 400; j++)
		{
			vecX << i-p1.x,j-p1.y,0;
			if (vec.dot(vecX)>0)
			{
				tmp = vec.cross(vecX).norm()/vec.norm();
			}
			else
			{
				tmp = vecX.norm();
			}
			field[i][j] = tmp;
		}
		
	}
	
}

double sigmoid(double x)
{
	double re;
	re = 1 / (1 + exp(-x/30));
	return re;
}

int main()
{
	srand((unsigned)time(NULL));
	point p1,p2,p3,p4,p_acute,p_sally,tmp;
	Eigen::Vector3d vecA,vecB,vecC,vec_acute,vec_mid,vec_sally,vecX,vecY;
	Eigen::Vector3d surface;
	bool isInGoodPlace = false;
	double dot,cross_direction,dotA,dotB,crossA,crossB;
	double tmp_distance;
	double crossYC,crossAB,crossAC;
	surface << 0,0,1; // 纸面向上
	bool is12Overlapped = true,is23Overlapped = true,is13Overlapped = true,isSameLine= true,isBlue = true;

	p1.x = rand() % 600 + 1;
	p1.y = rand() % 400 + 1;
	while (isSameLine)
	{
		is12Overlapped = true,is23Overlapped = true,is13Overlapped = true,isSameLine= true;
		while (is12Overlapped)
		{
			p2.x = rand() % 600 + 1;
			p2.y = rand() % 400 + 1;
			if (p2.x != p1.x || p2.y != p1.y)
			{
				is12Overlapped = false;
			}
			// printf("p2:%d,%d\n",p2.x, p2.y);
		}
		while (is13Overlapped || is23Overlapped)
		{
			p3.x = rand() % 600 + 1;
			p3.y = rand() % 400 + 1;
			if (p3.x != p1.x || p3.y != p1.y)
			{
				is13Overlapped = false;
			}
			if (p3.x != p2.x || p3.y != p2.y)
			{
				is23Overlapped = false;
			}	
		}
		if ((p3.y-p2.y)*(p3.x-p1.x) != (p3.y-p1.y)*(p3.x-p2.x))
		{
			isSameLine = false;
		}
	}
	
	vecA << p2.x-p1.x, p2.y-p1.y, 0;
	vecB << p3.x-p1.x, p3.y-p1.y, 0;

	while (!isInGoodPlace)
	{
		isInGoodPlace = false;
		p4.x = rand() % 600 + 1;
		p4.y = rand() % 400 + 1;
		vecC << p4.x-p2.x, p4.y-p2.y, 0;
		dot = vecA.dot(vecB);
		cross_direction = vecA.cross(vecB).dot(surface);
		dotA = vecC.dot(vecA);
		dotB = vecC.dot(vecB);
		crossA = vecC.cross(vecA).dot(surface);
		crossB = vecC.cross(vecB).dot(surface);
		if (dot > 0 && cross_direction > 0)
		{
			if ((dotA>0 && dotB>0 && crossA<0 && crossB>0) || (dotA>0 && crossA>0 && crossB>0))
			{
				isInGoodPlace = true;
			}
			
		}
		else if(dot < 0 && cross_direction > 0)
		{
			if ((dotA<0 && dotB>0 && crossA<0 && crossB>0) || (dotA<0 && crossA>0 && crossB<0))
			{
				isInGoodPlace = true;
			}
		}
		else if(dot > 0 && cross_direction < 0)
		{
			if ((dotA>0 && dotB>0 && crossA>0 && crossB<0) || (dotA>0 && crossA<0 && crossB<0))
			{
				isInGoodPlace = true;
			}
		}
		else if(dot < 0 && cross_direction < 0)
		{
			if ((dotA<0 && dotB>0 && crossA>0 && crossB<0) || (dotA<0 && crossA<0 && crossB>0))
			{
				isInGoodPlace = true;
			}
		}
		else
		{
			continue;
		}						
	}
	if (dot > 0)
	{
		p_acute = p1;
		p_sally = p2;
		vec_mid = vecA;
		vec_acute = vecB;
		vec_sally = vecC;
	}
	else if(dot < 0)
	{
		p_sally = p1;
		p_acute = p2;
		vec_mid << -vecA(0),-vecA(1),0;
		vec_acute = vecC;
		vec_sally = vecB;
	}

	for (int i = 0; i < 600; i++)
	{
		for (int j = 0; j < 400; j++)
		{
			tmp.x = i;
			tmp.y = j;
			vecX << tmp.x-p_acute.x, tmp.y-p_acute.y, 0;
			vecY << tmp.x-p_sally.x, tmp.y-p_sally.y, 0;
			crossAB = vec_mid.cross(vec_acute).dot(surface);
			crossAC = vec_mid.cross(vec_sally).dot(surface);
			dotA = vecX.dot(vec_mid);
			dotB = vecX.dot(vec_acute);
			crossA = vecX.cross(vec_mid).dot(surface);
			crossB = vecX.cross(vec_acute).dot(surface);
			crossYC = vecY.cross(vec_sally).dot(surface);
			
			if (crossAB > 0 && crossAC >0) //1
			{
				if (dotA>0 && dotB>0 && crossA<0 && crossB>0 && crossYC<0)
				{
					isGreenRegion[i][j] = 1;
				}
				
			}
			else if (crossAB>0 && crossAC<0) //2
			{
				if (dotA>0 && dotB>0 && crossA<0 && crossB>0)
				{
					isGreenRegion[i][j] = 1;
				}
				else if(dotA>0 &&crossA>0 && crossB>0 && crossYC<0)
				{
					isGreenRegion[i][j] = 1;
				}
			}
			else if(crossAB < 0 && crossAC<0) //3
			{
				if (dotA>0 && dotB>0 && crossA>0 && crossB<0 && crossYC>0)
				{
					isGreenRegion[i][j] = 1;
				}				
			}
			else if (crossAB<0 && crossAC>0) //4
			{
				if (dotA>0 && dotB>0 && crossA>0 && crossB<0)
				{
					isGreenRegion[i][j] = 1;
				}
				else if(dotA>0 &&crossA<0 && crossB<0 && crossYC>0)
				{
					isGreenRegion[i][j] = 1;
				}
			}

		}

	}
	
	distance_mid_generate(distance_mid,p1,p2);
	distance_angle_generate(distance_angle1,p1,p3);
	distance_angle_generate(distance_angle2,p2,p4);
	for (int i = 0; i < 600; i++)
	{
		for (int j = 0; j < 400; j++)
		{
			tmp_distance = my_min(distance_mid[i][j],distance_angle1[i][j]);
			distance_field[i][j] = my_min(tmp_distance,distance_angle2[i][j]);
		}
		
	}
	cv::Mat img = cv::Mat::zeros(cv::Size(600,400), CV_8UC3);

	for (int i = 0; i < 400; i++)
	{
		for (int j = 0; j < 600; j++)
		{
			if(isGreenRegion[j][i])
			{
				img.at<cv::Vec3b>(i,j)[0] = (int)(sigmoid(distance_field[j][i]/600)*255);
				img.at<cv::Vec3b>(i,j)[1] = (int)((distance_field[j][i]/600)*255);
			}
			else
			{
				img.at<cv::Vec3b>(i,j)[0] = (int)(sigmoid(distance_field[j][i])*255);
				img.at<cv::Vec3b>(i,j)[2] = (int)((distance_field[j][i]/600)*255);
			}
		}
		
	}
	

    cv::Point p_1(p1.x, p1.y);
	cv::Point p_2(p2.x, p2.y);
    cv::Point p_3(p3.x, p3.y);
    cv::Point p_4(p4.x, p4.y);

    line(img, p_1, p_2, cv::Scalar(255,255,255), 1);
    line(img, p_3, p_1, cv::Scalar(255,255,255), 1);
    line(img, p_2, p_4, cv::Scalar(255,255,255), 1);
    cv::imshow("img", img);
    cv::waitKey(0);			
	return 0;
}

